﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Text;
using Verification.Mold;

namespace Verification.ChartUtils
{
    public class ImageUtils
    {
        public enum ZoomType { NearestNeighborInterpolation, BilinearInterpolation }
        /// <summary>
        /// 图像缩放
        /// </summary>
        /// <param name="srcBmp">原始图像</param>
        /// <param name="width">目标图像宽度</param>
        /// <param name="height">目标图像高度</param>
        /// <param name="dstBmp">目标图像</param>
        /// <param name="GetNearOrBil">缩放选用的算法</param>
        /// <returns>处理成功 true 失败 false</returns>
        public static bool Zoom(Bitmap srcBmp, double ratioW, double ratioH, out Bitmap dstBmp, ZoomType zoomType= ZoomType.BilinearInterpolation)
        {//ZoomType为自定义的枚举类型
            if (srcBmp == null)
            {
                dstBmp = null;
                return false;
            }
            //若缩放大小与原图一样，则返回原图不做处理
            if ((ratioW == 1.0) && ratioH == 1.0)
            {
                dstBmp = new Bitmap(srcBmp);
                return true;
            }
            //计算缩放高宽
            double height = ratioH * (double)srcBmp.Height;
            double width = ratioW * (double)srcBmp.Width;
            dstBmp = new Bitmap((int)width, (int)height);

            BitmapData srcBmpData = srcBmp.LockBits(new Rectangle(0, 0, srcBmp.Width, srcBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            BitmapData dstBmpData = dstBmp.LockBits(new Rectangle(0, 0, dstBmp.Width, dstBmp.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
            unsafe
            {
                byte* srcPtr = null;
                byte* dstPtr = null;
                int srcI = 0;
                int srcJ = 0;
                double srcdI = 0;
                double srcdJ = 0;
                double a = 0;
                double b = 0;
                double F1 = 0;//横向插值所得数值
                double F2 = 0;//纵向插值所得数值
                if (zoomType == ZoomType.NearestNeighborInterpolation)
                {//邻近插值法

                    for (int i = 0; i < dstBmp.Height; i++)
                    {
                        srcI = (int)(i / ratioH);//srcI是此时的i对应的原图像的高
                        srcPtr = (byte*)srcBmpData.Scan0 + srcI * srcBmpData.Stride;
                        dstPtr = (byte*)dstBmpData.Scan0 + i * dstBmpData.Stride;
                        for (int j = 0; j < dstBmp.Width; j++)
                        {
                            dstPtr[j * 3] = srcPtr[(int)(j / ratioW) * 3];//j / ratioW求出此时j对应的原图像的宽
                            dstPtr[j * 3 + 1] = srcPtr[(int)(j / ratioW) * 3 + 1];
                            dstPtr[j * 3 + 2] = srcPtr[(int)(j / ratioW) * 3 + 2];
                        }
                    }
                }
                else if (zoomType == ZoomType.BilinearInterpolation)
                {//双线性插值法
                    byte* srcPtrNext = null;
                    for (int i = 0; i < dstBmp.Height; i++)
                    {
                        srcdI = i / ratioH;
                        srcI = (int)srcdI;//当前行对应原始图像的行数
                        srcPtr = (byte*)srcBmpData.Scan0 + srcI * srcBmpData.Stride;//指原始图像的当前行
                        srcPtrNext = (byte*)srcBmpData.Scan0 + (srcI + 1) * srcBmpData.Stride;//指向原始图像的下一行
                        dstPtr = (byte*)dstBmpData.Scan0 + i * dstBmpData.Stride;//指向当前图像的当前行
                        for (int j = 0; j < dstBmp.Width; j++)
                        {
                            srcdJ = j / ratioW;
                            srcJ = (int)srcdJ;//指向原始图像的列
                            if (srcdJ < 1 || srcdJ > srcBmp.Width - 1 || srcdI < 1 || srcdI > srcBmp.Height - 1)
                            {//避免溢出（也可使用循环延拓）
                                dstPtr[j * 3] = 255;
                                dstPtr[j * 3 + 1] = 255;
                                dstPtr[j * 3 + 2] = 255;
                                continue;
                            }
                            a = srcdI - srcI;//计算插入的像素与原始像素距离（决定相邻像素的灰度所占的比例）
                            b = srcdJ - srcJ;
                            for (int k = 0; k < 3; k++)
                            {//插值    公式：f(i+p,j+q)=(1-p)(1-q)f(i,j)+(1-p)qf(i,j+1)+p(1-q)f(i+1,j)+pqf(i+1, j + 1)
                                F1 = (1 - b) * srcPtr[srcJ * 3 + k] + b * srcPtr[(srcJ + 1) * 3 + k];
                                F2 = (1 - b) * srcPtrNext[srcJ * 3 + k] + b * srcPtrNext[(srcJ + 1) * 3 + k];
                                dstPtr[j * 3 + k] = (byte)((1 - a) * F1 + a * F2);
                            }
                        }
                    }
                }
            }
            srcBmp.UnlockBits(srcBmpData);
            dstBmp.UnlockBits(dstBmpData);
            return true;
        }
        /// <summary>
        /// 切割图片
        /// </summary>
        /// <param name="rowNum">y轴</param>
        /// <param name="colNum">x轴</param>
        /// <param name="srcBitmap">图片数据</param>
        /// <returns></returns>
        public static Bitmap[] getImageCut(int rowNum, int colNum, Bitmap srcBitmap)
        {
            int bitmapNum = rowNum * colNum;//图片数量
            Bitmap[] bitmapArr = new Bitmap[bitmapNum];
            int perWidth = srcBitmap.Width / colNum; //每个图片宽度
            int perHeight = srcBitmap.Height / rowNum;//每个图片高度
            int srcImageX = 0;
            int srcImageY = 0;
            for (int rowIdx = 0; rowIdx < rowNum; rowIdx++)
            {
                for (int colIdx = 0; colIdx < colNum; colIdx++)
                {
                    int curIdx = rowIdx * colNum + colIdx;
                    bitmapArr[curIdx] = new Bitmap(perWidth, perHeight);
                    Graphics newBmpGraphics = Graphics.FromImage(bitmapArr[curIdx]);//新图片
                    Rectangle destImageRect = new Rectangle(0, 0, perWidth, perHeight);//目标图片
                    Rectangle srcImageRect = new Rectangle(srcImageX, srcImageY, perWidth, perHeight);//原始图片
                    newBmpGraphics.DrawImage(srcBitmap, destImageRect, srcImageRect, GraphicsUnit.Pixel);
                    srcImageX += perWidth;
                }
                srcImageY += perHeight;
                srcImageX = 0;
            }
            return bitmapArr;
        }

        public static string[] BreakUpTheFigure(int x,int y,float w,float h,Bitmap image)
        {
            Bitmap[] bitMapData = new Bitmap[x * y];
            string[] base64Data = new string[x * y];
            bitMapData = ImageUtils.getImageCut(y, x, image);
            image.Dispose();
            GC.Collect();
            for (int i = 0; i < x * y; i++)
            {
                base64Data[i] = new Base64Utils().BitmapToBase64(bitMapData[i]);
            }
            return base64Data;
        }
    }
}
